<template>
    <el-radio-group v-model="currentStroke" class="radio-group">
        <el-radio
            :key="level"
            :label="level"
            v-for="(lable, level) in strokeList"
        >
            {{ lable }}
        </el-radio>
    </el-radio-group>
</template>

<script lang="ts">
import {
  Options, Vue, Emit, Prop, Watch,
} from 'vue-property-decorator';
import { ElRadioGroup, ElRadio } from 'element-plus';
import { drawImageRoundToCanvas, drawImageRoundRectToCanvas } from '../../../utils';

const paddingPx = 60;

interface IStrokeMap <T> {
    normal: T,
    roundedRectangle: T,
    circular: T,
}

@Options({
  components: {
    ElRadioGroup,
    ElRadio,
  },
})
export default class StrokeSelector extends Vue {
    @Prop({
      type: String,
    })
    image!:string;

    @Prop({
      type: String,
    })
    originalImage!: string;

    private currentStroke: keyof IStrokeMap<string> = 'normal';

    private currentImage = '';

    private get strokeList(): IStrokeMap<string> {
      return {
        normal: '原图',
        roundedRectangle: '圆角矩形描边',
        circular: '圆形描边',
      };
    }

    @Emit('update:image')
    @Watch('currentStroke')
    private async changeCurrentLevel(): Promise<string> {
      const handleMap: IStrokeMap<Function> = {
        normal: () => this.originalImage,
        roundedRectangle: () => this.addRoundLayer(true),
        circular: () => this.addRoundLayer(),
      };
      return await handleMap[this.currentStroke]();
    }

    @Watch('image', { immediate: true })
    private syncImage() {
      this.currentImage = this.image;
      this.changeCurrentLevel();
    }

    private async addRoundLayer(isRadius = false) {
      // 圆形需要绝对裁剪为正方形,圆角矩形保持原有的长宽比
      const canvas = await this.createCanvas(!isRadius);
      if (isRadius) {
        await drawImageRoundRectToCanvas(
          canvas,
          this.originalImage,
          { dx: paddingPx / 2, dy: paddingPx / 2 },
          40,
          { strokeStyle: '#fff', lineWidth: paddingPx },
        );
      } else {
        await drawImageRoundToCanvas(
          canvas,
          this.originalImage,
          { dx: paddingPx / 2, dy: paddingPx / 2 },
          { strokeStyle: '#fff', lineWidth: paddingPx },
        );
      }
      return canvas.toDataURL('image/png');
    }

    private async createCanvas(isClip = false): Promise<HTMLCanvasElement> {
      const { width, height } = await this.getImageSize();
      const [canvasWidth, canvasHeight] = [width + paddingPx, height + paddingPx];
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      if (!ctx) { return Promise.reject(Error('canvas is Error')); }
      if (isClip) { // 裁剪为绝对正方形
        const length = Math.min(canvasWidth, canvasHeight);
        canvas.setAttribute('width', `${length}px`);
        canvas.setAttribute('height', `${length}px`);
      } else { // 保留原有图片尺寸比例
        canvas.setAttribute('width', `${canvasWidth}px`);
        canvas.setAttribute('height', `${canvasHeight}px`);
      }
      return canvas;
    }

    private getImageSize(): Promise<{width: number, height: number}> {
      const image = new Image();
      image.src = this.originalImage;
      return new Promise((resolve) => {
        image.onload = () => {
          resolve({
            width: image.width,
            height: image.height,
          });
        };
      });
    }
}
</script>

<style lang='less' scoped>
.radio-group {
    :deep(.el-radio) {
        margin-right: 10px;
        &:last-child {
            margin-right: 0;
        }
        .el-radio__inner {
            font-size: 11px;
        }
        .el-radio__label{
            padding-left: 2px;
            font-size: 11px;
            color: #898989;
        }
    }
}
</style>
